#include "include.H"
extern UART_HandleTypeDef huart1;

void printfdec_u32(uint32_t dat)
{
	//HAL_UART_Transmit(&huart1, (uint8_t*)dat, 4, 1000);
	char str[16];
	sprintf(str, "%d ", (int)dat);
	printf(str);
}

/************************************************************
*	ProjectName:	   LT8911
*	FileName:	       LT8911.c
*	BuildData:	     2018-05-24
*	Version��        V1.0
* 	Author:          xhguo
* 	Company:	     Lontium
************************************************************/
#include "include.h"

u16 hact, vact;
u16 hs, vs;
u16 hbp, vbp;
u16 htotal, vtotal;
u16 hfp, vfp;
//u8 VideoFormat=0;

#define LVDS_PORT_CNT 1

VideoFormat Video_Format;
//															           //hfp, hs, hbp,hact,htotal,vfp, vs, vbp, vact,vtotal,
video_timing video_640x480_60Hz = {8, 96, 40, 640, 800, 33, 2, 10, 480, 525, 25000};
video_timing video_720x480_60Hz = {16, 62, 60, 720, 858, 9, 6, 30, 480, 525, 27000};
video_timing video_1280x720_60Hz = {110, 40, 220, 1280, 1650, 5, 5, 20, 720, 750, 74250};
video_timing video_1280x720_30Hz = {110, 40, 220, 1280, 1650, 5, 5, 20, 720, 750, 74250};
video_timing video_1366x768_60Hz = {26, 110, 110, 1366, 1592, 13, 6, 13, 768, 800, 81000};
//struct video_timing video_1280x1024_60Hz   ={100,100,208,1280,  1688,  5,  5,  32, 1024, 1066, 107960};
video_timing video_1920x1080_30Hz = {88, 44, 148, 1920, 2200, 4, 5, 36, 1080, 1125, 74250};
video_timing video_1920x1080_60Hz = {88, 44, 148, 1920, 2200, 4, 5, 36, 1080, 1125, 148500};
video_timing video_3840x1080_60Hz = {176, 88, 296, 3840, 4400, 4, 5, 36, 1080, 1125, 297000};
video_timing video_1920x1200_60Hz = {48, 32, 80, 1920, 2080, 3, 6, 26, 1200, 1235, 154000};
video_timing video_3840x2160_30Hz = {176, 88, 296, 3840, 4400, 8, 10, 72, 2160, 2250, 297000};
video_timing video_3840x2160_60Hz = {176, 88, 296, 3840, 4400, 8, 10, 72, 2160, 2250, 594000};

void LT9211_ChipID(void)
{
	HDMI_WriteI2C_Byte(0xff, 0x81); //register bank
	printf("\r\nLT9211 Chip ID:%x,", HDMI_ReadI2C_Byte(0x00));
	printf("%x, ", HDMI_ReadI2C_Byte(0x01));
	printf("%x, ", HDMI_ReadI2C_Byte(0x02));
}

void LT9211_SystemInt(void)
{
	/* system clock init */
	HDMI_WriteI2C_Byte(0xff, 0x82);
	HDMI_WriteI2C_Byte(0x01, 0x18);

	HDMI_WriteI2C_Byte(0xff, 0x86);
	HDMI_WriteI2C_Byte(0x06, 0x61);
	HDMI_WriteI2C_Byte(0x07, 0xa8); //fm for sys_clk

	HDMI_WriteI2C_Byte(0xff, 0x87); //��ʼ�� txpll �Ĵ����б�Ĭ��ֵ������
	HDMI_WriteI2C_Byte(0x14, 0x08); //default value
	HDMI_WriteI2C_Byte(0x15, 0x00); //default value
	HDMI_WriteI2C_Byte(0x18, 0x0f);
	HDMI_WriteI2C_Byte(0x22, 0x08); //default value
	HDMI_WriteI2C_Byte(0x23, 0x00); //default value
	HDMI_WriteI2C_Byte(0x26, 0x0f);
}

void LT9211_LvdsRxPhy(void)
{
	/* Mipi rx phy */
	HDMI_WriteI2C_Byte(0xff, 0x82);
	HDMI_WriteI2C_Byte(0x02, 0x88); //lvds rx enable
	HDMI_WriteI2C_Byte(0x05, 0x21); //port A CK lane swap
	HDMI_WriteI2C_Byte(0x0d, 0x21);

#ifdef _Input_PortA_
	/*port a*/
	HDMI_WriteI2C_Byte(0x07, 0x1f); //port clk enable  ��ֻ��Portbʱ,porta��lane0 clkҪ�򿪣�
	HDMI_WriteI2C_Byte(0x04, 0xa0);

//portA PN swap
//HDMI_WriteI2C_Byte(0x09,0xFC); //port a diff swap
#endif
#ifdef _Input_PortB_
	/*port b*/
	HDMI_WriteI2C_Byte(0x0f, 0x1f); //port clk enable
	HDMI_WriteI2C_Byte(0x10, 0x00); //portb clk sel
	HDMI_WriteI2C_Byte(0x04, 0xa1);

	HDMI_WriteI2C_Byte(0x11, 0x01); //port b diff swap
#endif

	/*port lane swap*/
	HDMI_WriteI2C_Byte(0xff, 0x86);
	HDMI_WriteI2C_Byte(0x33, 0xe4); //port a lane swap
	HDMI_WriteI2C_Byte(0x34, 0xe4); //port b lane swap

	HDMI_WriteI2C_Byte(0xff, 0x81);
	HDMI_WriteI2C_Byte(0x20, 0x7f);
	HDMI_WriteI2C_Byte(0x20, 0xff); //mlrx calib reset
}

void LT9211_ClockCheckDebug(void)
{
#ifdef _uart_debug_
	u32 fm_value;

	HDMI_WriteI2C_Byte(0xff, 0x86);
	HDMI_WriteI2C_Byte(0x00, 0x01);
	HAL_Delay(300);
	fm_value = 0;
	fm_value = (HDMI_ReadI2C_Byte(0x08) & (0x0f));
	fm_value = (fm_value << 8);
	fm_value = fm_value + HDMI_ReadI2C_Byte(0x09);
	fm_value = (fm_value << 8);
	fm_value = fm_value + HDMI_ReadI2C_Byte(0x0a);
	printf("\r\nporta clock: ");
	printfdec_u32(fm_value);

	HDMI_WriteI2C_Byte(0xff, 0x86);
	HDMI_WriteI2C_Byte(0x00, 0x02);
	HAL_Delay(100);
	fm_value = 0;
	fm_value = (HDMI_ReadI2C_Byte(0x08) & (0x0f));
	fm_value = (fm_value << 8);
	fm_value = fm_value + HDMI_ReadI2C_Byte(0x09);
	fm_value = (fm_value << 8);
	fm_value = fm_value + HDMI_ReadI2C_Byte(0x0a);
	printf("\r\nportb clock: ");
	printfdec_u32(fm_value);

	HDMI_WriteI2C_Byte(0xff, 0x86);
	HDMI_WriteI2C_Byte(0x00, 0x0a);
	HAL_Delay(100);
	fm_value = 0;
	fm_value = (HDMI_ReadI2C_Byte(0x08) & (0x0f));
	fm_value = (fm_value << 8);
	fm_value = fm_value + HDMI_ReadI2C_Byte(0x09);
	fm_value = (fm_value << 8);
	fm_value = fm_value + HDMI_ReadI2C_Byte(0x0a);
	printf("\r\npix clock: ");
	printfdec_u32(fm_value);

	HDMI_WriteI2C_Byte(0xff, 0x86);
	HDMI_WriteI2C_Byte(0x00, 0x12);
	HAL_Delay(100);
	fm_value = 0;
	fm_value = (HDMI_ReadI2C_Byte(0x08) & (0x0f));
	fm_value = (fm_value << 8);
	fm_value = fm_value + HDMI_ReadI2C_Byte(0x09);
	fm_value = (fm_value << 8);
	fm_value = fm_value + HDMI_ReadI2C_Byte(0x0a);
	printf("\r\nbyte clock: ");
	printfdec_u32(fm_value);
#endif
}

void LT9211_LvdsRxDigital(void)
{

	HDMI_WriteI2C_Byte(0xff, 0xd8);

	if (LVDS_PORT_CNT == 1)
	{
		HDMI_WriteI2C_Byte(0x10, 0x80); //0x80: 1port, 0x00: 2port
		printf("\r\n LvdsRxDigital: set lvds port count = 1");
	}
	else if (LVDS_PORT_CNT == 2)
	{
		HDMI_WriteI2C_Byte(0x10, 0x00); //0x80: 1port, 0x00: 2port
		printf("\r\n LvdsRxDigital: set lvds port count = 2");
	}

	else
	{
		printf("\r\n LvdsRxDigital: lvds port count error");
	}

	HAL_Delay(10);
	HDMI_WriteI2C_Byte(0xff, 0x81);
	HDMI_WriteI2C_Byte(0x10, 0xbe);
	HDMI_WriteI2C_Byte(0x10, 0xfe); //video chk soft rst
	HDMI_WriteI2C_Byte(0x0c, 0xeb);
	HDMI_WriteI2C_Byte(0x0c, 0xfb); //lvds rx logic rst

	HDMI_WriteI2C_Byte(0xff, 0x86);
	HDMI_WriteI2C_Byte(0x30, 0x45); //port ab input port sel

	HDMI_WriteI2C_Byte(0xff, 0x85);
	HDMI_WriteI2C_Byte(0x88, 0x10); // LVDS to MIPI ; rx_tx_sel

#ifdef lvds_format_JEIDA
	HDMI_WriteI2C_Byte(0xff, 0x85);
	HDMI_WriteI2C_Byte(0x59, 0xd0);
	HDMI_WriteI2C_Byte(0xff, 0xd8);
	HDMI_WriteI2C_Byte(0x11, 0x40);
#endif

	HDMI_WriteI2C_Byte(0xff, 0xf9);
	//HDMI_WriteI2C_Byte(0x86, 0x0f);
	//HDMI_WriteI2C_Byte(0x87, 0x30);
}

void LT9211_LvdsRxPll(void)
{
	u8 loopx;
	HDMI_WriteI2C_Byte(0xff, 0x82);
	HDMI_WriteI2C_Byte(0x25, 0x05);
	HDMI_WriteI2C_Byte(0x27, 0x02);

	if (LVDS_PORT_CNT == 1)
	{
		HDMI_WriteI2C_Byte(0x24, 0x24); //RXPLL_LVDSCLK_MUXSEL,PIXCLK_MUXSEL	0x2c.
		HDMI_WriteI2C_Byte(0x28, 0x44); //0x64
		printf("\r\n LvdsRxPll: set lvds port count = 1");
	}
	else if (LVDS_PORT_CNT == 2)
	{
		HDMI_WriteI2C_Byte(0x24, 0x2c); //RXPLL_LVDSCLK_MUXSEL,PIXCLK_MUXSEL	0x2c.
		HDMI_WriteI2C_Byte(0x28, 0x64); //0x64
		printf("\r\n LvdsRxPll: set lvds port count = 2");
	}
	else
	{
		printf("\r\n LvdsRxPll: lvds port count error");
	}
	HAL_Delay(10);
	HDMI_WriteI2C_Byte(0xff, 0x87);
	HDMI_WriteI2C_Byte(0x05, 0x00);
	HDMI_WriteI2C_Byte(0x05, 0x80);
	HAL_Delay(1000);
	for (loopx = 0; loopx < 10; loopx++) //Check Rx PLL cal
	{

		HDMI_WriteI2C_Byte(0xff, 0x87);
		if (HDMI_ReadI2C_Byte(0x12) & 0x80)
		{
			if (HDMI_ReadI2C_Byte(0x11) & 0x80)
			{
				printf("\r\nLT9211 rx cal done");
			}
			else
			{
				printf("\r\nLT9211 rx cal undone!!");
			}
			printf("\r\nLT9211 rx pll lock");
			break;
		}
		else
		{
			printf("\r\nLT9211 rx pll unlocked");
		}
	}
}

void LT9211_MipiTxpll(void)
{
	u8 loopx;

	HDMI_WriteI2C_Byte(0xff, 0x82);
	HDMI_WriteI2C_Byte(0x36, 0x03);
	HDMI_WriteI2C_Byte(0x37, 0x28); //MIPI TX Byte CLK:104MHz
	HDMI_WriteI2C_Byte(0x38, 0x14);
	HDMI_WriteI2C_Byte(0x3a, 0x98);
	// HDMI_WriteI2C_Byte(0x3b,0x44);

	HDMI_WriteI2C_Byte(0xff, 0x87);
	HDMI_WriteI2C_Byte(0x13, 0x80);
	HDMI_WriteI2C_Byte(0x14, 0x08);
	HDMI_WriteI2C_Byte(0x15, 0x00);
	
	HDMI_WriteI2C_Byte(0xff, 0x81);
	HDMI_WriteI2C_Byte(0x11, 0xfd);
	HDMI_WriteI2C_Byte(0x11, 0xff);
	

	
	
	HAL_Delay(100);
	for (loopx = 0; loopx < 10; loopx++) //Check Tx PLL cal done
	{

		HDMI_WriteI2C_Byte(0xff, 0x87);
		if (HDMI_ReadI2C_Byte(0x1f) & 0x80)
		{
			if (HDMI_ReadI2C_Byte(0x20) & 0x80)
			{
				printf("\r\nLT9211 tx pll lock");
			}
			else
			{
				printf("\r\nLT9211 tx pll unlocked");
			}
			printf("\r\nLT9211 tx pll cal done");
			break;
		}
		else
		{
			printf("\r\nLT9211 tx pll unlocked");
		}
	}
}

void LT9211_MipiTxPhy(void)
{
	HDMI_WriteI2C_Byte(0xff, 0x82);
	HDMI_WriteI2C_Byte(0x62, 0x00); //ttl output disable
	HDMI_WriteI2C_Byte(0x3b, 0x32); //mipi en
}

void LT9211_MipiTxDigital(void)
{
	HDMI_WriteI2C_Byte(0xff, 0xd4);
	HDMI_WriteI2C_Byte(0x1c, 0x30); //hs_rqst_pre
	HDMI_WriteI2C_Byte(0x1d, 0x0a); //lpx
	HDMI_WriteI2C_Byte(0x1e, 0x06); //prpr
	HDMI_WriteI2C_Byte(0x1f, 0x0a); //trail
	HDMI_WriteI2C_Byte(0x21, 0x00); //[5]byte_swap,[0]burst_clk

	HDMI_WriteI2C_Byte(0xff, 0x86);
	HDMI_WriteI2C_Byte(0x40, 0x80); //tx_src_sel
	/*port src sel*/
	HDMI_WriteI2C_Byte(0x41, 0x01);
	HDMI_WriteI2C_Byte(0x42, 0x23);
	HDMI_WriteI2C_Byte(0x43, 0x40); //pt0_tx_src_sel
	HDMI_WriteI2C_Byte(0x44, 0x12);
	HDMI_WriteI2C_Byte(0x45, 0x34); //pt1_tx_src_scl

	/*HDMI_WriteI2C_Byte(0xff, 0xd4);
	HDMI_WriteI2C_Byte(0x16, 0x55);
	HDMI_WriteI2C_Byte(0x10, 0x01);
	HDMI_WriteI2C_Byte(0x11, 0x50); //read byteclk ���ֵ�Ĵ�
	HDMI_WriteI2C_Byte(0x13, 0x0f); //bit[5:4]:lane num, bit[2]:bllp,bit[1:0]:vid_mode
	HDMI_WriteI2C_Byte(0x14, 0x20); //bit[5:4]:data typ,bit[2:0]:fmt sel 000:rgb888
	HDMI_WriteI2C_Byte(0x21, 0x00);*/
	
	HDMI_WriteI2C_Byte(0xff, 0xd4);
	HDMI_WriteI2C_Byte(0x16, 0x55);
	HDMI_WriteI2C_Byte(0x10, 0x01);
	HDMI_WriteI2C_Byte(0x11, 0x50);
	HDMI_WriteI2C_Byte(0x13, 0x02);
	HDMI_WriteI2C_Byte(0x14, 0x20);
	HDMI_WriteI2C_Byte(0x21, 0x00);
}

void LT9211_SetTxTiming(void)
{
	u8 sync_polarity;
	u16 hact, vact;
	u16 hs, vs;
	u16 hbp, vbp;
	u16 htotal, vtotal;
	u16 hfp, vfp;
	Timing TimingStr;
	HDMI_WriteI2C_Byte(0xff, 0x86);
	sync_polarity = HDMI_ReadI2C_Byte(0x70);
	vs = HDMI_ReadI2C_Byte(0x71);

	hs = HDMI_ReadI2C_Byte(0x72);
	hs = (hs << 8) + HDMI_ReadI2C_Byte(0x73);

	vbp = HDMI_ReadI2C_Byte(0x74);
	vfp = HDMI_ReadI2C_Byte(0x75);

	hbp = HDMI_ReadI2C_Byte(0x76);
	hbp = (hbp << 8) + HDMI_ReadI2C_Byte(0x77);

	hfp = HDMI_ReadI2C_Byte(0x78);
	hfp = (hfp << 8) + HDMI_ReadI2C_Byte(0x79);

	vtotal = HDMI_ReadI2C_Byte(0x7A);
	vtotal = (vtotal << 8) + HDMI_ReadI2C_Byte(0x7B);

	htotal = HDMI_ReadI2C_Byte(0x7C);
	htotal = (htotal << 8) + HDMI_ReadI2C_Byte(0x7D);

	vact = HDMI_ReadI2C_Byte(0x7E);
	vact = (vact << 8) + HDMI_ReadI2C_Byte(0x7F);

	hact = HDMI_ReadI2C_Byte(0x80);
	hact = (hact << 8) + HDMI_ReadI2C_Byte(0x81);

	TimingStr.hact = hact;
	TimingStr.vact = vact;
	TimingStr.vs = vs;
	TimingStr.vbp = vbp;
	TimingStr.vfp = vfp;

	HDMI_WriteI2C_Byte(0xff, 0xd4);
	HDMI_WriteI2C_Byte(0x04, 0x08);						 //hs[7:0] not care
	HDMI_WriteI2C_Byte(0x05, 0x08);						 //hbp[7:0] not care
	HDMI_WriteI2C_Byte(0x06, 0x08);						 //hfp[7:0] not care
	HDMI_WriteI2C_Byte(0x07, (u8)(TimingStr.hact >> 8)); //hactive[15:8]
	HDMI_WriteI2C_Byte(0x08, (u8)(TimingStr.hact));		 //hactive[7:0]

	HDMI_WriteI2C_Byte(0x09, (u8)(TimingStr.vs));		 //vfp[7:0]
	HDMI_WriteI2C_Byte(0x0a, 0x00);						 //bit[3:0]:vbp[11:8]
	HDMI_WriteI2C_Byte(0x0b, (u8)(TimingStr.vbp));		 //vbp[7:0]
	HDMI_WriteI2C_Byte(0x0c, (u8)(TimingStr.vact >> 8)); //vcat[15:8]
	HDMI_WriteI2C_Byte(0x0d, (u8)(TimingStr.vact));		 //vcat[7:0]
	HDMI_WriteI2C_Byte(0x0e, (u8)(TimingStr.vfp >> 8));  //vfp[11:8]
	HDMI_WriteI2C_Byte(0x0f, (u8)(TimingStr.vfp));		 //vfp[7:0]

	printf("\r\nsync_polarity = %x", sync_polarity);
	printf("\r\nhfp, hs, hbp, hact, htotal = ");
	printfdec_u32(hfp);
	printfdec_u32(hs);
	printfdec_u32(hbp);
	printfdec_u32(hact);
	printfdec_u32(htotal);

	printf("\r\nvfp, vs, vbp, vact, vtotal = ");
	printfdec_u32(vfp);
	printfdec_u32(vs);
	printfdec_u32(vbp);
	printfdec_u32(vact);
	printfdec_u32(vtotal);
}

void LT9211_Config(void)
{
	LT9211_ChipID();
	LT9211_SystemInt();
	LT9211_LvdsRxPhy();
	LT9211_LvdsRxDigital();
	LT9211_LvdsRxPll();

	LT9211_MipiTxpll();
	LT9211_MipiTxPhy();
	InitPanel();
	LT9211_SetTxTiming();
	LT9211_MipiTxDigital();
	LT9211_ClockCheckDebug();
}
